package bleudp

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"iot-ble-server/dgram"
	"iot-ble-server/global/globalconstants"
	"iot-ble-server/global/globallogger"
	"iot-ble-server/global/globalmemo"
	"iot-ble-server/global/globalredis"
	"iot-ble-server/global/globalsocket"
	"iot-ble-server/global/globalstruct"
	"iot-ble-server/global/globalutils"
	"iot-ble-server/internal/config"
	"iot-ble-server/internal/packets"
	"iot-ble-server/internal/storage"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"

	"github.com/redis/go-redis/v9"
)

//`解码上行数据使用`
//hello ack消息处理
func procHelloAck(ctx context.Context, jsoninfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Infof("<procHello> [Gateway DevEui: %s] start proc hello msg", devEui)
	if UpdateSockets(ctx, jsoninfo.MessageBody.GwMac, jsoninfo.Rinfo) { //更新成功后继续执行，否则就放弃
		newJsonInfo := packets.JsonUdpInfo{}
		// gwInfo, err := procDevHttp(jsoninfo.MessageBody.GwMac)
		// if err != nil {
		// 	globallogger.Log.Errorf("<procHelloAck> [DevEui: %s] has error %v", devEui, err)
		// 	return
		// }
		// gwStatus, _ := strconv.Atoi(gwInfo.OnlineStatus)
		// switch gwStatus {
		// case globalconstants.DEV_STATUS_ONLINE: //在线
		// 	mqttMsg := globalstruct.GwMessageMqtt{
		// 		Device: jsoninfo.MessageBody.GwMac,
		// 	}
		// 	mqttMsg.Data = make([]globalstruct.DeviceData, 1)
		// 	mqttMsg.Data[0] = globalstruct.DeviceData{
		// 		TS: int(time.Now().UnixMilli()),
		// 		Value: &globalstruct.InnerValue{
		// 			AliveTime: 15,
		// 		},
		// 	}
		// 	jsonMsg, err := json.Marshal(mqttMsg)
		// 	if err != nil {
		// 		globallogger.Log.Errorf("<procHelloAck> Publish[keepalive]: Json marshaling failed %v", err)
		// 	}
		// 	Publish(globalconstants.TopicV3GatewayTelemetry, string(jsonMsg))
		// case globalconstants.DEV_STATUS_DISABLE: //离线或未启用
		// 	globallogger.Log.Errorf("<procHelloAck> current Gateway [DevEui: %s] status not support process", devEui)
		// default:
		// 	jsonMsg, err := json.Marshal(globalstruct.GwMqtt{
		// 		Device: jsoninfo.MessageBody.GwMac,
		// 	})
		// 	if err != nil {
		// 		globallogger.Log.Errorf("<procHelloAck> Publish[online]: Json marshaling failed %v", err)
		// 	}
		// 	Publish(globalconstants.TopicV3GatewayOnline, string(jsonMsg))
		// }
		// if gwStatus != globalconstants.DEV_STATUS_DISABLE {
		reMsgHeader := packets.MessageHeader{
			Version:        jsoninfo.MessageHeader.Version,
			LinkMsgFrameSN: jsoninfo.MessageHeader.LinkMsgFrameSN,
			LinkMsgType:    jsoninfo.MessageHeader.LinkMsgType,
			OpType:         packets.Response,
		}
		newJsonInfo.MessageHeader = reMsgHeader
		newJsonInfo.PendCtrl = globalconstants.CtrlLinkedMsgHeader
		sendBytes, err := EnCodeForDownUdpMessage(newJsonInfo)
		if err != nil {
			globallogger.Log.Errorf("<procHelloAck> [DevEui: %s] has error %v", devEui, err)
			return
		}
		SendDownMessage(sendBytes, jsoninfo.MessageBody.GwMac, jsoninfo.MessageBody.GwMac)
		//} else {
		//	globallogger.Log.Errorf("<procHelloAck> [DevEui: %s] response ack failed", devEui, err)
		//}
	}
}

//设备的HTTP请求
func procDevHttp(devMac string) (globalstruct.DeviceInfo, error) {
	var (
		devStatusInfo = globalstruct.DeviceInfo{}
		deviceMsg     = globalstruct.DeviceHttpMsg{}
		queryStr      = fmt.Sprintf(globalconstants.DeviceURL, devMac)
		err           error
		bodyByte      []byte
		waitDealData  map[string]interface{}
		ok            bool
		needVar       interface{}
	)
	resp, err := http.Get(queryStr)
	if err != nil {
		return devStatusInfo, errors.New("get http request error")
	}
	defer resp.Body.Close()
	bodyByte, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return devStatusInfo, err
	}
	err = json.Unmarshal(bodyByte, &deviceMsg)
	if err != nil {
		return devStatusInfo, err
	}
	if deviceMsg.Code != globalconstants.HTTP_CODE_SUCCESS {
		return devStatusInfo, errors.New(deviceMsg.Message)
	}
	waitDealData, ok = deviceMsg.Data.(map[string]interface{})
	if !ok {
		return devStatusInfo, errors.New("get http request body error")
	}
	if needVar, ok = waitDealData["onlineStatus"]; ok {
		devStatusInfo.OnlineStatus = int(needVar.(float64))
		devStatusInfo.DeviceSN = devMac
	} else {
		err = errors.New("get http request body loss onlineStatus infomation")
	}
	return devStatusInfo, err
}

//此事devEUI可以表示为网关插卡+物联网模块
//暂行
func procIotModuleStatus(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Infof("<procIotModuleStatus> [DevEui: %s] start proc Iotmodule status change msg", devEui)
	moduleId, _ := strconv.ParseUint(jsonInfo.MessageBody.TLV.TLVPayload.IotModuleId, 16, 16)
	moduleStatus, _ := strconv.ParseUint(jsonInfo.MessageBody.TLV.TLVPayload.IotModuleStatus, 16, 16)
	//应答消息
	go func(info packets.JsonUdpInfo, mac string) {
		globallogger.Log.Infof("<procIotModuleStatus> [DevEui: %s] send Iotmodule status change response msg", devEui)
		info.MessageHeader.OpType = packets.Response
		info.MessageBody = packets.MessageBody{
			GwMac: mac,
		}
		info.PendCtrl = globalconstants.CtrlLinkedMsgHeadWithBoy
		byteToSend, err := EnCodeForDownUdpMessage(info)
		if err != nil {
			globallogger.Log.Errorf("<procIotModuleStatus> [DevEui: %s] generate byte info failed %v", devEui, err)
			return
		}
		SendDownMessage(byteToSend, devEui, mac)
	}(jsonInfo, jsonInfo.MessageBody.GwMac)
	//通知平台
	go func() {
		globallogger.Log.Infof("<procIotModuleStatus> [DevEui: %s] Publish[telemetry] Iotmodule status change", devEui)
		mqttMsg := &globalstruct.GwMessageMqtt{
			Device: jsonInfo.MessageBody.GwMac,
		}
		mqttMsg.Data = make([]globalstruct.DeviceData, 1)
		mqttMsg.Data[0] = globalstruct.DeviceData{
			TS: int(time.Now().UnixMilli()),
			Value: &globalstruct.InnerValue{
				ModuleInfo: &globalstruct.IotModuleState{
					PortID: int(moduleId),
					State:  int(moduleStatus),
				},
			},
		}
		jsonMsg, err := json.Marshal(mqttMsg)
		if err != nil {
			globallogger.Log.Errorf("<procIotModuleStatus> Publish[telemetry] Json marshaling failed %v", err)
			return
		}
		Publish(globalconstants.TopicV3GatewayTelemetry, string(jsonMsg))
	}()
	devReq, err := GenerateDownJsonInfo(ctx, &globalstruct.DownJsonInfoUnify{
		GwMac:         jsonInfo.MessageBody.GwMac,
		IotModuleId:   jsonInfo.MessageBody.TLV.TLVPayload.IotModuleId,
		LinkedMsgType: packets.GatewayDevInfo,
		Ctrl:          globalconstants.CtrlLinkedMsgHeadWithBoy,
	})
	if err != nil {
		globallogger.Log.Errorf("<procIotModuleStatus> [DevEui: %s] generate devInfo has error %v", devEui, err)
		return
	}
	byteToSend, err := EnCodeForDownUdpMessage(devReq)
	if err != nil {
		globallogger.Log.Errorf("<procIotModuleStatus> [DevEui: %s] generate devInfo byte info failed %v", devEui, err)
		return
	}
	SendMsgBeforeDown(ctx, byteToSend, devReq.MessageHeader.LinkMsgFrameSN, "", "", devReq.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID, jsonInfo.MessageHeader.LinkMsgType)
}

//更新网络信息
func UpdateSockets(ctx context.Context, gwMac string, rinfo dgram.RInfo) bool {
	globallogger.Log.Infof("<UpdateSockets> [DevEui: %s] Update Socket", gwMac)
	cacheKey := globalutils.CreateCacheKey(globalconstants.GwSocketCachePrefix, gwMac)
	socketInfo := &globalstruct.SocketInfo{}
	preCacheData := globalstruct.SocketInfo{
		Mac:        gwMac,
		Family:     rinfo.Family,
		IPAddr:     rinfo.Address,
		IPPort:     rinfo.Port,
		UpdateTime: time.Now(),
	}
	var (
		cacheDataByte    []byte
		cachedSocketByte []byte
		err              error
	)
	cacheDataByte, err = json.Marshal(preCacheData) //待存入数据
	if err != nil {
		globallogger.Log.Errorln("<UpdateSockets> gateway info marshal fail")
		return false
	}
	if config.C.General.UseRedis {
		strSocketInfo, err1 := globalredis.RedisCache.Get(ctx, cacheKey).Result()
		if err1 != nil {
			if err1 != redis.Nil {
				globallogger.Log.Errorf("<UpdateSockets> redis has error %v", err1)
				return false
			}
			globalredis.RedisCache.Set(ctx, cacheKey, cacheDataByte, time.Second*time.Duration(globalconstants.TimeoutUDPLinked))
			return true
		}
		cachedSocketByte = []byte(strSocketInfo)
	} else {
		cachedSocketByte, err = globalmemo.SocketFreeCache.Get([]byte(cacheKey))
		if err != nil {
			globalmemo.SocketFreeCache.Set([]byte(cacheKey), cacheDataByte, globalconstants.TimeoutUDPLinked)
			return true
		}
	}
	err = json.Unmarshal(cachedSocketByte, &socketInfo)
	if err != nil {
		globallogger.Log.Errorln("<UpdateSockets> gateway info unmarshal failed")
		return false
	}
	// if rinfo.Address != socketInfo.IPAddr || rinfo.Family != socketInfo.Family || rinfo.Port != socketInfo.IPPort { //区分缓存数据库，现在缓存就每次都写
	// 	globallogger.Log.Warnf("<UpdateSockets> [DevEui: %s] Update Socket information", gwMac)
	if config.C.General.UseRedis {
		_, err = globalredis.RedisCache.Set(ctx, cacheKey, cacheDataByte, time.Second*time.Duration(globalconstants.TimeoutUDPLinked)).Result()
		if err != nil {
			globallogger.Log.Errorln("<UpdateSockets> gateway info store redis failed", err)
			return false
		}
	} else {
		globalmemo.SocketFreeCache.Set([]byte(cacheKey), cacheDataByte, globalconstants.TimeoutUDPLinked)
	}
	//数据库暂时不用
	// pgSocketSet := map[string]interface{}{
	// 	"gwmac":      gwMac,
	// 	"family":     preCacheData.Family,
	// 	"ipaddr":     preCacheData.IPAddr,
	// 	"ipport":     preCacheData.IPPort,
	// 	"updatetime": preCacheData.UpdateTime,
	// }
	// err = storage.FindSocketAndUpdatePG(pgSocketSet)
	// if err != nil {
	// 	globallogger.Log.Errorln("<updateSockets> [DevEui: %s] update PG failed", err)
	// }
	// } else {

	// }
	return true
}

// 消息下行接口
func SendDownMessage(data []byte, devEui, gwMac string) bool {
	var (
		socketInfo          *globalstruct.SocketInfo
		err                 error
		socketInfoBytes     []byte
		cacheKey, socketVal string
	)
	cacheKey = globalutils.CreateCacheKey(globalconstants.GwSocketCachePrefix, gwMac)
	if config.C.General.UseRedis {
		socketVal, err = globalredis.RedisCache.Get(context.TODO(), cacheKey).Result()
		socketInfoBytes = []byte(socketVal)
	} else {
		socketInfoBytes, err = globalmemo.SocketFreeCache.Get([]byte(cacheKey))
	}
	if err != nil && err != redis.Nil {
		globallogger.Log.Errorf("<SendDownMessage> [GwMac:%s] [DevEui: %s] send failed errors: %v", gwMac, devEui, err)
		return false
	}
	if len(socketInfoBytes) == 0 {
		socketInfo, err = storage.FindSocketByGwMac(gwMac)
		if err != nil {
			globallogger.Log.Errorf("<SendDownMessage> [DevEui: %s] send fail, can't find right socket to send msg, reseaon: %v", devEui, err)
			return false
		}
	} else {
		json.Unmarshal(socketInfoBytes, &socketInfo)
	}
	if socketInfo == nil {
		globallogger.Log.Errorf("<SendDownMessage> [DevEui: %s] miss corresponding socket information", devEui)
	} else if socketInfo.Family == "IPv6" {
		globallogger.Log.Errorf("<SendDownMessage> [DevEui: %s] current unsupport IPv6", devEui)
	} else {
		err = globalsocket.ServiceSocket.Send(data, socketInfo.IPPort, socketInfo.IPAddr)
		if err != nil {
			globallogger.Log.Errorf("<SendDownMessage> [DevEui: %s] send message occur error %v", devEui, err)
			return false
		}
	}
	return true
}

//终端广播报文能处理, 唯一映射即可
//连接|断联以后才会有连接状态 首次情况下肯定没有
//`收到连接报文的时候还需要重新设置设备相关连接状态`
//暂时不使用redis进行记录
//devMac [网关+插卡] 相关信息
func procBleBoardCast(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Infof("<procBleBoardCast> [DevEui: %s] start deal ble boardcast message", devEui)
	var curNode globalstruct.TerminalInfo
	rssi, _ := strconv.ParseUint(jsonInfo.MessageBody.TLV.TLVPayload.RSSI, 16, 8)
	secondCacheKey := globalutils.CreateCacheKey(jsonInfo.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID)
	for _, curTLV := range jsonInfo.MessageAppBody.MultiTLV {
		curNode = globalstruct.TerminalInfo{
			TerminalName: curTLV.TLVPayload.DevMac,
			TerminalMac:  curTLV.TLVPayload.DevMac,
			GwMac:        jsonInfo.MessageBody.GwMac,
			IotModuleId:  jsonInfo.MessageBody.ModuleID,
			RSSI:         int8(rssi),
			TimeStamp:    time.Now(),
		}
		gwInfo, ok := globalmemo.MemoCacheDownPriority.Get(curTLV.TLVPayload.DevMac)
		if !ok {
			tempGwMap := make(map[string]globalstruct.TerminalInfo)
			tempGwMap[secondCacheKey] = curNode
			globalmemo.MemoCacheDownPriority.Set(curTLV.TLVPayload.DevMac, tempGwMap)
		} else {
			gwInfo.(map[string]globalstruct.TerminalInfo)[secondCacheKey] = curNode
			globalmemo.MemoCacheDownPriority.Set(curTLV.TLVPayload.DevMac, gwInfo)
		}
		//此处获取最优节点
		gwInfo, _ = globalmemo.MemoCacheDownPriority.Get(curTLV.TLVPayload.DevMac)
		priorityNode := globalstruct.TerminalInfo{
			RSSI: -128,
		}
		for _, node := range gwInfo.(map[string]globalstruct.TerminalInfo) {
			if node.RSSI > priorityNode.RSSI {
				priorityNode = node
			}
		}
		if curTLV.TLVPayload.NoticeContent.ManuData.Data.AdData.CompData.MsgType == "0104" ||
			curTLV.TLVPayload.NoticeContent.ManuData.Data.AdData.CompData.MsgType == "0102" {
			var err error
			// var (
			// 	jsonMsg []byte
			// 	err     error
			// )
			// devInfo, err := procDevHttp(curTLV.TLVPayload.DevMac)
			// if err != nil {
			// 	globallogger.Log.Errorf("<procBleBoardCast> [DevEui: %s] has error %v", devEui, err)
			// 	return
			// }
			// switch devInfo.OnlineStatus {
			// case globalconstants.DEV_STATUS_DISABLE:
			// 	globallogger.Log.Errorf("<procBleBoardCast> [DevEui: %s] unsupport operation", devEui)
			// 	return
			// default:
			// 	jsonMsg, err = json.Marshal(globalstruct.DevMessageMqtt{
			// 		Device: curTLV.TLVPayload.DevMac,
			// 	})
			// 	if err != nil {
			// 		globallogger.Log.Errorf("<procBleBoardCast> Publish: Json marshal failed")
			// 		return
			// 	}
			// 	Publish(globalconstants.TopicV3DeviceOnline, string(jsonMsg))
			// }
			// jsonMsg, err = json.Marshal(globalstruct.DevMessageMqtt{
			// 	Device: curTLV.TLVPayload.DevMac,
			// 	Data:   curTLV.TLVPayload.NoticeData,
			// 	Metadata: map[string]int8{
			// 		"rssi": priorityNode.RSSI,
			// 	},
			// })
			// if err != nil {
			// 	globallogger.Log.Errorf("<procBleBoardCast> Publish: Json marshal failed %v", err)
			// 	return
			// }
			// Publish(globalconstants.TopicV3DeviceTelemetry, string(jsonMsg))
			if curTLV.TLVPayload.NoticeContent.ManuData.Data.AdData.CompData.MsgType == globalconstants.ManufactureConnMarked {
				go func(deviceData, devMac string) {
					if len(deviceData) > 0 {
						eventFlags, _ := strconv.ParseUint(deviceData, 16, 8)
						if eventFlags&1 == 1 { //需要时间同步
							globalmemo.MemoBleTimeSynchron.Set(devMac, true)
						}
					}
				}(curTLV.TLVPayload.NoticeContent.ManuData.Data.AdData.CompData.DeviceData, curTLV.TLVPayload.DevMac)
				err = ConnectBleDev(ctx, priorityNode)
				if err != nil {
					if strings.Contains(err.Error(), "Repeat") {
						globallogger.Log.Infof("<procBleBoardCast> deal [DevEui: %s] connect fail ,error is %v", curTLV.TLVPayload.DevMac, err)
					} else {
						globallogger.Log.Errorf("<procBleBoardCast> deal [DevEui: %s] connect fail ,error is %v", curTLV.TLVPayload.DevMac, err)
					}
				}
			}
		}
	}
}

//确认消息时生成缓存
func procBleConfirm(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procBleConfirm> [DevEui %s] start deal ble confirm message", devEui)
	if jsonInfo.MessageAppBody.ErrorCode != packets.Success { //错误码生效前有效
		globallogger.Log.Errorf("<procBleConfirm> [DevEui %s] start deal ble confirm message, msgType is %s, reason is %s ", devEui, jsonInfo.MessageAppHeader.Type, packets.GetResult(jsonInfo.MessageAppBody.ErrorCode, packets.English))
	}
	if DealWithConfirm(ctx, jsonInfo.MessageHeader.LinkMsgFrameSN, jsonInfo.MessageAppHeader.SN, "procBleConfirm", jsonInfo.MessageBody.ModuleID, jsonInfo.MessageBody.GwMac) {
		cacheKeyResp := globalutils.CreateCacheKey(globalconstants.BleDevCacheMessageResponsePrefix, jsonInfo.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID, jsonInfo.MessageAppBody.RespondFrame)
		if config.C.General.UseRedis {
			_, err := globalredis.RedisCache.Set(ctx, cacheKeyResp, []byte{1}, -1).Result()
			if err != nil {
				globallogger.Log.Errorf("<procBleConfirm> redis has error %v", err)
			}
		} else {
			globalmemo.BleFreeCacheDevResponseInfo.Set([]byte(cacheKeyResp), []byte{1}, 0)
		}
	}
}

//处理应答信息
func procBleResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Infof("<procBleResponse> [DevEui %s] start deal ble response message, ble msg type is %v", devEui, jsonInfo.MessageAppBody.TLV.TLVMsgType)
	switch jsonInfo.MessageAppBody.TLV.TLVMsgType {
	case packets.TLVScanRespMsg:
		//procScanResponse(ctx, jsonInfo, devEui)
	case packets.TLVConnectRespMsg:
		procBleConnResponse(ctx, jsonInfo, devEui)
	case packets.TLVMainServiceRespMsg:
		procBleMainServiceResponse(ctx, jsonInfo, devEui)
	case packets.TLVCharFindRespMsg:
		//procBleCharFindResponse(ctx, jsonInfo, devEui)
	case packets.TLVMainServiceByUUIDRespMsg:
		procBleUUIDServiceResponse(ctx, jsonInfo, devEui)
	case packets.TLVCharConfRespMsg:
		procBleCharacterConfResponse(ctx, jsonInfo, devEui)
	case packets.TLVCharOptRespMsg:
		procBleCharacterOptionResponse(ctx, jsonInfo, devEui)
	default:
		globallogger.Log.Errorf("<procBleResponse> [DevEui: %s] received unrecognized message type: %s", devEui, jsonInfo.MessageAppBody.TLV.TLVMsgType)
	}
}

//处理特征操作应答
func procBleCharacterOptionResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Infof("<procBleCharacterOptionResponse> [DevEui: %s] start deal characterOptionResponse", devEui)
	/*处理特征操作*/
}

//处理连接应答
//处理应答需要pop数据
// 连接成功前检测该消息是否超时
func procBleConnResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Warnf("<procBleConnResponse> [DevEui: %s] start deal ble connect response message", devEui)
	if DealWithBleResponse(ctx, jsonInfo.MessageAppBody.RespondFrame, jsonInfo.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID) {
		connDevInfo := globalstruct.TerminalInfo{
			TerminalMac:   jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac,
			GwMac:         jsonInfo.MessageBody.GwMac,
			ConnectStatus: "01", //正常已连接
			IotModuleId:   jsonInfo.MessageBody.ModuleID,
			ConnHandle:    jsonInfo.MessageAppBody.TLV.TLVPayload.ConnHandle,
		}
		connCacheKey := globalutils.CreateCacheKey(globalconstants.BleDevCacheConnPrefix, connDevInfo.TerminalMac)
		InfoByte, err := json.Marshal(connDevInfo)
		if err != nil {
			globallogger.Log.Errorf("<procBleConnResponse> [DevEui: %s] change data has error %v", err)
			return
		}
		if config.C.General.UseRedis {
			_, err = globalredis.RedisCache.Set(ctx, connCacheKey, InfoByte, 0).Result()
			if err != nil {
				globallogger.Log.Errorf("<procBleConnResponse> [DevEui: %s] redis can't work %v", err)
				return
			}
		} else {
			globalmemo.BleFreeCacheDevConnInfo.Set([]byte(connCacheKey), InfoByte, 0)
		}
		//开始主服务发现
		err = SearchMainService(ctx, connDevInfo)
		if err != nil {
			globallogger.Log.Errorf("<procBleConnResponse> has error %v", err)
		}
	}
}

// //处理扫描应答
// func procScanResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
// 	globallogger.Log.Infof("<procScanResponse> DevEui %s start deal ble scan response message\n", devEui)
// 	if jsonInfo.MessageAppBody.ErrorCode != packets.Success {
// 		globallogger.Log.Errorf("<procScanResponse> DevEui %s has an error %v\n", devEui, packets.GetResult(jsonInfo.MessageAppBody.ErrorCode, packets.English).String())
// 		return
// 	}
// 	curSN, _ := strconv.ParseInt(jsonInfo.MessageAppHeader.SN, 16, 16)
// 	verifyFrame := CheckUpMessageFrame(ctx, jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac, int(curSN))
// 	if verifyFrame != globalconstants.TERMINAL_CORRECT { //目前仅后面
// 		return //消息响应校对，若校准正确则继续执行，否则抛出
// 	}
// 	curTime := time.Now()
// 	passTime, ok := globalmemo.MemoCacheScanTimeOut.Get(jsonInfo.MessageBody.GwMac + jsonInfo.MessageBody.ModuleID)
// 	tempTime, _ := strconv.ParseInt(jsonInfo.MessageAppBody.TLV.TLVPayload.ScanTimeout, 16, 32)
// 	limitTime := time.Duration(tempTime) * time.Millisecond
// 	if !ok || globalutils.CompareTimeIsExpire(curTime, passTime.(time.Time), limitTime) {
// 		globallogger.Log.Errorf("<procScanResponse> DevEui %s scan timeout, unable to perform subsequent connections\n", devEui)
// 		return
// 	}
// }

//处理主服务报文应答, 这个deveui应当描述的是设备mac
//主服务先存缓存，然后再存数据库， 查看缓存中的信息是否发生更改，更改则清空数据库相关内容，重新写入
//自身缓存则多加一级: 是否为主服务放置在最后
//这一步之前需要将所有的信息处理完成后才进行后续操作
func procBleMainServiceResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procBleMainServiceResponse> [DevEui: %s] start deal ble mainservice response message", devEui)
	var err error
	if DealWithBleResponse(ctx, jsonInfo.MessageAppBody.RespondFrame, jsonInfo.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID) {
		serviceHandleWithUUID := make(map[string]string, 0)
		if config.C.General.UseRedis {
			pipe := globalredis.RedisCache.Pipeline()
			for _, serviceTLV := range jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve {
				serviceHandleWithUUID[serviceTLV.TLVPayload.ServiceHandle] = serviceTLV.TLVPayload.ServiceUUID
				pipe.HSet(ctx, globalutils.CreateCacheKey(globalconstants.DEV_SERVICE, devEui), serviceTLV.TLVPayload.ServiceHandle, serviceTLV.TLVPayload.Primary)
			}
			_, err = pipe.Exec(ctx)
			if err != nil {
				globallogger.Log.Errorf("<procBleMainServiceResponse> [DevEui: %s] redis has error %v", devEui, err)
				return
			}
		} else {
			serviceMap := make(map[string]string)
			for _, serviceTLV := range jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve {
				serviceHandleWithUUID[serviceTLV.TLVPayload.ServiceHandle] = serviceTLV.TLVPayload.ServiceUUID
				serviceMap[serviceTLV.TLVPayload.ServiceHandle] = serviceTLV.TLVPayload.Primary
				globalmemo.MemoCacheService.Set(globalutils.CreateCacheKey(globalconstants.DEV_SERVICE, devEui), serviceMap)
			}
		}
		if len(serviceHandleWithUUID) != 0 {
			var terminalInfo globalstruct.TerminalInfo
			cacheKey := globalutils.CreateCacheKey(globalconstants.BleDevCacheConnPrefix, jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac)
			if config.C.General.UseRedis {
				strInfo, err1 := globalredis.RedisCache.Get(ctx, cacheKey).Result()
				if err1 != nil {
					globallogger.Log.Errorf("<procBleMainServiceResponse> [DevEui %s] loss connect dev infomation", devEui)
					return
				}
				err1 = json.Unmarshal([]byte(strInfo), &terminalInfo)
				if err1 != nil {
					globallogger.Log.Errorf("<procBleMainServiceResponse> [DevEui %s] connect redis infomation has error %v\n", devEui, err1)
					return
				}
			} else {
				byteInfo, err1 := globalmemo.BleFreeCacheDevConnInfo.Get([]byte(cacheKey))
				if err1 != nil {
					globallogger.Log.Errorf("<procBleMainServiceResponse> [DevEui %s] loss connect dev infomation\n", devEui)
					return
				}
				err1 = json.Unmarshal(byteInfo, &terminalInfo)
				if err1 != nil {
					globallogger.Log.Errorf("<procBleMainServiceResponse> [DevEui %s] connect memo infomation has error %v", devEui, err1)
					return
				}
			}
			for _, uuid := range serviceHandleWithUUID { //特定服务下发
				if (len(uuid) == 32 && uuid[4:8] == globalconstants.NusServiceUUID) || uuid == globalconstants.NusServiceUUID {
					err1 := SearchMainServiceUUID(ctx, terminalInfo, uuid)
					if err1 != nil {
						globallogger.Log.Errorf("<procBleMainServiceResponse> [DevEui %s] search main service error %v", devEui, err1)
					}
					break //目前配置下仅针对唯一服务
				}
			}
		} else {
			globallogger.Log.Warnf("<procBleMainServiceResponse> [DevEui %s] not have right service", devEui)
		}
	}
}

//处理特征值响应
//devEui通常为设备mac
//存储缓存为设备服务唯一标识： 特征handle : 对应值(默认)
//特征值映射完成
// func procBleCharFindResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
// 	globallogger.Log.Infof("<procBleCharFindResponse> DevEui %s start deal ble characterValue response message\n", devEui)
// 	var err error
// 	if DealWithResponseBle(ctx, jsonInfo.MessageHeader.LinkMsgFrameSN, jsonInfo.MessageAppHeader.SN, "procBleCharFindResponse", jsonInfo.MessageAppBody.ErrorCode, devEui) {
// 		if config.C.General.UseRedis {
// 			pipe := globalredis.RedisCache.Pipeline()
// 			for _, characterTLV := range jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve {
// 				cacheKey := globalutils.CreateCacheKey(devEui, globalconstants.DEV_CHARACTER, characterTLV.TLVPayload.ServiceHandle)
// 				pipe.HSet(ctx, cacheKey, characterTLV.TLVPayload.CharHandle, globalconstants.DEV_CHARACTER_DEFAULT)
// 			}
// 			_, err = pipe.Exec(ctx)
// 			if err != nil {
// 				globallogger.Log.Errorf("<procBleMainServiceResponse> DevEui %s redis has error %v \n", devEui, err)
// 				return
// 			}
// 		} else {
// 			if len(jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve) != 0 {
// 				characterMap := make(map[string]int)
// 				cacheKey := globalutils.CreateCacheKey(devEui, globalconstants.DEV_CHARACTER, jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve[0].TLVPayload.ServiceHandle)
// 				for _, characterTLV := range jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve {
// 					characterMap[characterTLV.TLVPayload.CharHandle] = globalconstants.DEV_CHARACTER_DEFAULT
// 				}
// 				globalmemo.MemoCacheServiceForChar.Set(cacheKey, characterMap)
// 			}
// 		}
// 	}
// }

//针对特定UUID的缓存生成
//服务key(devmac + service)
//默认一个uuid服务
func procBleUUIDServiceResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procBleUUIDServiceResponse> [DevEui: %s] start deal ble uuid service response message", devEui)
	var (
		err        error
		reserveLen = len(jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve)
	)
	if DealWithBleResponse(ctx, jsonInfo.MessageAppBody.RespondFrame, jsonInfo.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID) &&
		reserveLen > 0 {
		allMessageTLV := globalstruct.ServiceCharacterMap{}
		allMessageTLVChar := globalstruct.CharacterServiceMap{}
		uuidForhandleSvc := make(map[string]string)
		uuidForhandleChar := make(map[string]string)
		serviceTLV, characterTLV, characterDesp := make([]packets.TLV, 0), make([]packets.TLV, 0), make([]packets.TLV, 0)
		for _, curTLV := range jsonInfo.MessageAppBody.TLV.TLVPayload.TLVReserve {
			if curTLV.TLVMsgType == packets.TLVServiceMsg {
				serviceTLV = append(serviceTLV, curTLV)
				uuidForhandleSvc[curTLV.TLVPayload.ServiceHandle] = curTLV.TLVPayload.ServiceUUID
			} else if curTLV.TLVMsgType == packets.TLVCharacteristicMsg {
				characterTLV = append(characterTLV, curTLV)
				uuidForhandleChar[curTLV.TLVPayload.CharHandle] = curTLV.TLVPayload.CharacterUUID
			} else {
				characterDesp = append(characterDesp, curTLV)
			}
		}
		allMessageTLV.ServiceMap = make(map[string]map[string]globalstruct.ServiceCharacterNode)
		allMessageTLVChar.CharacterMap = make(map[string]globalstruct.ServiceCharacterNode)
		for _, service := range serviceTLV {
			allMessageTLV.ServiceMap[service.TLVPayload.ServiceHandle] = make(map[string]globalstruct.ServiceCharacterNode)
		}
		for _, character := range characterTLV {
			tempNode := globalstruct.ServiceCharacterNode{
				ServiceUUID:     uuidForhandleSvc[character.TLVPayload.ServiceHandle],
				ServiceHandle:   character.TLVPayload.ServiceHandle,
				CharUUID:        character.TLVPayload.CharacterUUID,
				CharacterHandle: character.TLVPayload.CharHandle,
				Properties:      character.TLVPayload.Properties,
			}
			allMessageTLV.ServiceMap[character.TLVPayload.ServiceHandle][character.TLVPayload.CharHandle] = globalstruct.ServiceCharacterNode{
				CharUUID:        character.TLVPayload.CharacterUUID,
				CharacterHandle: character.TLVPayload.CharHandle,
			}
			allMessageTLVChar.CharacterMap[character.TLVPayload.CharHandle] = tempNode
		}
		for _, charDesp := range characterDesp {
			node := allMessageTLVChar.CharacterMap[charDesp.TLVPayload.CharHandle]
			node.CCCDHanle = charDesp.TLVPayload.CCCDHandle
			allMessageTLVChar.CharacterMap[charDesp.TLVPayload.CharHandle] = node
			allMessageTLV.ServiceMap[charDesp.TLVPayload.ServiceHandle][charDesp.TLVPayload.CharHandle] = node
		}
		serviceKey := globalutils.CreateCacheKey(globalconstants.BleDevSeviceToCharacterPrifix, jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac)
		characterKey := globalutils.CreateCacheKey(globalconstants.BleDevCharacterToSevicePrifix, jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac)
		serviceByte, err1 := json.Marshal(allMessageTLV)
		characterByte, err2 := json.Marshal(allMessageTLVChar)
		if err1 != nil || err2 != nil {
			globallogger.Log.Errorf("<procBleUUIDServiceResponse> marshal msg has error err1:%v, err2:%v", err1, err2)
			return
		}
		if config.C.General.UseRedis { //覆盖式存储
			pipe := globalredis.RedisCache.Pipeline()
			pipe.Set(ctx, serviceKey, serviceByte, -1)
			pipe.Set(ctx, characterKey, characterByte, -1)
			_, err = pipe.Exec(ctx)
			if err != nil {
				globallogger.Log.Errorf("<procBleUUIDServiceResponse> redis has error %v", err)
				return
			}
		} else {
			globalmemo.BleCacheServiceForChar.Set([]byte(serviceKey), serviceByte, 0)
			globalmemo.BleCacheCharacterForSvc.Set([]byte(characterKey), characterByte, 0)
		}
		//发起特征值配置请求
		var terminalInfo globalstruct.TerminalInfo
		connCacheKey := globalutils.CreateCacheKey(globalconstants.BleDevCacheConnPrefix, jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac)
		if config.C.General.UseRedis {
			strInfo, err1 := globalredis.RedisCache.Get(ctx, connCacheKey).Result()
			if err1 != nil {
				globallogger.Log.Errorf("<procBleUUIDServiceResponse> [DevEui %s] loss connect dev infomation", devEui)
				return
			}
			err1 = json.Unmarshal([]byte(strInfo), &terminalInfo)
			if err1 != nil {
				globallogger.Log.Errorf("<procBleUUIDServiceResponse> [DevEui %s] connect redis infomation has error %v", devEui, err1)
				return
			}
		} else {
			byteInfo, err1 := globalmemo.BleFreeCacheDevConnInfo.Get([]byte(connCacheKey))
			if err1 != nil {
				globallogger.Log.Errorf("<procBleUUIDServiceResponse> [DevEui %s] loss connect dev infomation", devEui)
				return
			}
			err1 = json.Unmarshal(byteInfo, &terminalInfo)
			if err1 != nil {
				globallogger.Log.Errorf("<procBleUUIDServiceResponse> [DevEui %s] connect memo infomation has error %v", devEui, err1)
				return
			}
		}
		err1 = CharacterConfig(ctx, terminalInfo, allMessageTLVChar.CharacterMap)
		if err1 != nil {
			globallogger.Log.Errorf("<procBleUUIDServiceResponse> [DevEui %s] character config has error %v", devEui, err1)
		}

	}
}

//处理特征配置应答
//将里面的特征值参数配置给改过来 修改某个服务中的cccd特征值改变
func procBleCharacterConfResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procBleCharacterConfResponse> DevEui %s start deal ble uuid service response message", devEui)
	if DealWithBleResponse(ctx, jsonInfo.MessageAppBody.RespondFrame, jsonInfo.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID) {
		cacheCharacterKey := globalutils.CreateCacheKey(globalconstants.BleDevCharacterToSevicePrifix, jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac)
		var (
			allCharacterMsg  globalstruct.CharacterServiceMap
			characterByteMap []byte
			characterStrMap  string
			err              error
		)
		if config.C.General.UseRedis {
			characterStrMap, err = globalredis.RedisCache.Get(ctx, cacheCharacterKey).Result()
			if err != nil {
				globallogger.Log.Errorf("<procBleCharacterConfResponse> DevEui %s redis has problem %v", err)
				return
			}
			characterByteMap = []byte(characterStrMap)
		} else {
			characterByteMap, err = globalmemo.BleCacheCharacterForSvc.Get([]byte(cacheCharacterKey))
			if err != nil {
				globallogger.Log.Errorf("<procBleCharacterConfResponse> DevEui %s memo has problem %v", err)
				return
			}
		}
		err = json.Unmarshal(characterByteMap, &allCharacterMsg)
		if err != nil {
			globallogger.Log.Errorf("<procBleCharacterConfResponse> DevEui %s unmarshal failed %v", err)
			return
		}
		tempCharacterMap := make(map[string]globalstruct.ServiceCharacterNode, 0)
		for handle, node := range allCharacterMsg.CharacterMap {
			if node.CharacterHandle == jsonInfo.MessageAppBody.TLV.TLVPayload.CharHandle &&
				node.CCCDHanle == jsonInfo.MessageAppBody.TLV.TLVPayload.CCCDHandle {
				node.CCCDHanleValue = jsonInfo.MessageAppBody.TLV.TLVPayload.CCCDHandleValue
			}
			tempCharacterMap[handle] = node
		}
		reBuildCharacterServiceMap := globalstruct.CharacterServiceMap{
			CharacterMap: tempCharacterMap,
		}
		byteToDown, err1 := json.Marshal(reBuildCharacterServiceMap)
		if err1 != nil {
			globallogger.Log.Errorf("<procBleCharacterConfResponse> [DevEui: %s] marshal failed %v\n", err1)
		}
		if config.C.General.UseRedis {
			globalredis.RedisCache.Set(ctx, cacheCharacterKey, byteToDown, -1).Result()
		} else {
			globalmemo.BleCacheCharacterForSvc.Set([]byte(cacheCharacterKey), byteToDown, 0)
		}

		//看是否需要进行时间同步
		if _, ok := globalmemo.MemoBleTimeSynchron.Get(jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac); ok {
			utcTime := time.Now().UTC().Unix()
			var terminalInfo globalstruct.TerminalInfo
			hexStrTime := strconv.FormatInt(utcTime, 16)
			strTimeSynChron := "00" + hexStrTime
			connCacheKey := globalutils.CreateCacheKey(globalconstants.BleDevCacheConnPrefix, jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac)
			if config.C.General.UseRedis {
				strInfo, err1 := globalredis.RedisCache.Get(ctx, connCacheKey).Result()
				if err1 != nil {
					globallogger.Log.Errorf("<procBleCharacterConfResponse> [DevEui %s] loss connect dev infomation", devEui)
					return
				}
				err1 = json.Unmarshal([]byte(strInfo), &terminalInfo)
				if err1 != nil {
					globallogger.Log.Errorf("<procBleCharacterConfResponse> [DevEui %s] connect redis infomation has error %v", devEui, err1)
					return
				}
			} else {
				byteInfo, err1 := globalmemo.BleFreeCacheDevConnInfo.Get([]byte(connCacheKey))
				if err1 != nil {
					globallogger.Log.Errorf("<procBleCharacterConfResponse> [DevEui %s] loss connect dev infomation", devEui)
					return
				}
				err1 = json.Unmarshal(byteInfo, &terminalInfo)
				if err1 != nil {
					globallogger.Log.Errorf("<procBleCharacterConfResponse> [DevEui %s] connect memo infomation has error %v", devEui, err1)
					return
				}
			}
			err1 := CharacterOptBleDev(ctx, terminalInfo, strTimeSynChron)
			if err1 != nil {
				globallogger.Log.Errorf("<CharacterOptBleDev> [DevEui %s] characterOptBleDev has error %v", devEui, err1)
				return
			}
			globalmemo.MemoBleTimeSynchron.Remove(jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac)
		}
	}
}

//处理特征通告， 暂时不存特征值
func procBleCharacteristicNotice(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procBleCharacteristicNotice> [DevEui: %s] start deal ble character notice message", devEui)
	go func(devMac string, characterValue string) {
		jsonMsg, err := json.Marshal(globalstruct.DevMessageMqtt{
			Device: devMac,
			Data:   characterValue,
		})
		if err != nil {
			globallogger.Log.Errorf("<procBleBoardCast> Publish: Json marshaling failed %v", err)
			return
		}
		Publish(globalconstants.TopicV3DeviceTelemetry, string(jsonMsg))
	}(jsonInfo.MessageAppBody.TLV.TLVPayload.DevMac, jsonInfo.MessageAppBody.TLV.TLVPayload.CharHandleValue)
	//下行开始应答
	jsonInfo.MessageAppBody.ErrorCode = packets.Success
	jsonInfo.MessageAppBody.TLV = packets.TLV{}
	jsonInfo.MessageAppHeader.OpType = packets.Response
	jsonInfo.MessageHeader.OpType = packets.Request
	jsonInfo.PendCtrl = globalconstants.CtrlAllMsg
	byteToSend, err := EnCodeForDownUdpMessage(jsonInfo)
	globalutils.BytesToHex(byteToSend)
	if err != nil {
		globallogger.Log.Errorf("<procBleCharacteristicNotice> [DevEui: %s] generate down message failed %v", devEui, err)
		return
	}
	SendMsgBeforeDown(ctx, byteToSend, jsonInfo.MessageHeader.LinkMsgFrameSN, jsonInfo.MessageAppHeader.SN, devEui, jsonInfo.MessageBody.GwMac, jsonInfo.MessageBody.ModuleID, packets.BleCharacteristicNotice)
}

//处理蓝牙终端断开连接情况
//连接只做了内容
func procBleTerminalDisConnect(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procBleTerminalDisConnect> [DevEui: %s] start deal ble terminal disconnect event message", devEui)
	for _, curTLV := range jsonInfo.MessageAppBody.MultiTLV {
		connCacheKey := globalutils.CreateCacheKey(globalconstants.BleDevCacheConnPrefix, curTLV.TLVPayload.DevMac)
		var (
			terminal     globalstruct.TerminalInfo
			err          error
			strTerminal  string
			byteTerminal []byte
		)
		if config.C.General.UseRedis {
			strTerminal, err = globalredis.RedisCache.Get(ctx, connCacheKey).Result()
			if err != nil {
				globallogger.Log.Errorf("<procBleTerminalDisConnect> [DevEui: %s] loss connect dev infomation", devEui)
				continue
			}
			err = json.Unmarshal([]byte(strTerminal), &terminal)
		} else {
			byteTerminal, err = globalmemo.BleFreeCacheDevConnInfo.Get([]byte(connCacheKey))
			if err != nil {
				globallogger.Log.Errorf("<procBleTerminalDisConnect> [DevEui: %s] has already disconnect", curTLV.TLVPayload.DevMac)
				continue
			}
			err = json.Unmarshal(byteTerminal, &terminal)
		}
		if err != nil {
			globallogger.Log.Errorf("<procBleTerminalDisConnect> [DevEui: %s] unmarshal failed %v", devEui, err)
			continue
		}
		terminal.ConnectStatus = "00" //断开连接标识
		byteTerminal, err = json.Marshal(terminal)
		if err != nil {
			globallogger.Log.Errorf("<procBleTerminalDisConnect> [DevEui: %s] has marshal data failed", curTLV.TLVPayload.DevMac)
			return
		}
		if config.C.General.UseRedis {
			_, err = globalredis.RedisCache.Set(ctx, connCacheKey, byteTerminal, -1).Result()
			if err != nil {
				globallogger.Log.Errorf("<procBleTerminalDisConnect> [DevEui: %s] restore redis has error %v", curTLV.TLVPayload.DevMac, err)
			}
		} else {
			globalmemo.BleFreeCacheDevConnInfo.Set([]byte(connCacheKey), byteTerminal, 0)
		}
	}
}

//处理网关设备请求响应
func procGatewayDevInfoResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procGatewayDevInfoResponse> [DevEui: %s] start deal GwDevice response", devEui)
	if DealWithConfirm(ctx, jsonInfo.MessageHeader.LinkMsgFrameSN, "", "procGatewayDevInfoResponse", "", jsonInfo.MessageBody.GwMac) {
		if jsonInfo.MessageBody.ErrorCode != packets.Success {
			globallogger.Log.Errorf("<procGatewayDevInfoResponse> [DevEui: %s] get error response %v", jsonInfo.MessageBody.ErrorCode)
			return
		}
		mqttMsg := globalstruct.GwMessageMqtt{
			Device: jsonInfo.MessageBody.GwMac,
		}
		mqttMsg.Data = make([]globalstruct.DeviceData, 2)
		portId, _ := strconv.Atoi(jsonInfo.MessageBody.TLV.TLVPayload.IotModuleId)
		mqttMsg.Data[0] = globalstruct.DeviceData{
			TS: int(time.Now().UnixMilli()),
			Value: &globalstruct.InnerValue{
				Basic: &globalstruct.BasicInfo{
					Model: jsonInfo.MessageBody.TLV.TLVPayload.TLVReserve[0].TLVPayload.TLVReserve[0].TLVPayload.GwType,
					SN:    jsonInfo.MessageBody.TLV.TLVPayload.TLVReserve[0].TLVPayload.TLVReserve[1].TLVPayload.GwSN,
					MAC:   jsonInfo.MessageBody.TLV.TLVPayload.TLVReserve[0].TLVPayload.TLVReserve[2].TLVPayload.GwMac,
				},
			},
		}
		mqttMsg.Data[1] = globalstruct.DeviceData{
			TS: int(time.Now().UnixMilli()),
			Value: &globalstruct.InnerValue{
				ModuleInfo: &globalstruct.IotModuleState{
					PortID: int(portId),
					Model:  jsonInfo.MessageBody.TLV.TLVPayload.TLVReserve[1].TLVPayload.IotModuleType,
					SN:     jsonInfo.MessageBody.TLV.TLVPayload.TLVReserve[2].TLVPayload.IotModuleSN,
					MAC:    jsonInfo.MessageBody.TLV.TLVPayload.TLVReserve[3].TLVPayload.IotModuleMac,
				},
			},
		}
		jsonMsg, err := json.Marshal(mqttMsg)
		if err != nil {
			globallogger.Log.Errorf("<procGatewayDevInfoResponse> Publish[telemetry] Json marshaling failed %v\n", err)
			return
		}
		Publish(globalconstants.TopicV3GatewayTelemetry, string(jsonMsg))
	}
}

//此处上送消息的类型还未知
func procIotModuleResponse(ctx context.Context, jsonInfo packets.JsonUdpInfo, devEui string) {
	globallogger.Log.Errorf("<procIotModuleResponse> [DevEui: %s] start deal iotmodule response", devEui)
	if DealWithConfirm(ctx, jsonInfo.MessageHeader.LinkMsgFrameSN, "", "procIotModuleResponse", "", jsonInfo.MessageBody.GwMac) {
		if jsonInfo.MessageBody.ErrorCode != packets.Success {
			mqttMsg := globalstruct.GwMqtt{
				Device: jsonInfo.MessageBody.GwMac,
				Data:   packets.GetResult(jsonInfo.MessageBody.ErrorCode, packets.English).String(),
			}
			jsonMsg, err := json.Marshal(mqttMsg)
			if err != nil {
				globallogger.Log.Errorf("<procGatewayDevInfoResponse> Publish[telemetry] Json marshaling failed %v\n", err)
				return
			}
			Publish(globalconstants.TopicV3GatewayTelemetry, string(jsonMsg))
		}
	}
}
